﻿namespace File_Renamer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.IO;

    class Renamer
    {
        public Renamer()
        {
             this.Files = new List<FileName>();
             this.ShouldSuggestFix = false;
        }

        public IEnumerable<FileName> Files { get; private set; }

        public string Folder { get; set; }

        public string RegEx { get; set; }

        public bool ShouldSuggestFix { get; set; }

        public bool CapsFix { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public void ChangeFileNames()
        {
            StreamWriter logFile = new StreamWriter("results.tsv");

            try
            {
                foreach (FileName file in this.Files)
                {
                    try
                    {
                        File.Move(file.FullName, file.NewFullName);
                        logFile.WriteLine("{0}\t {1}.{2}", file.FullName, file.NewName, file.Extension);
                    }
                    catch (IOException ex)
                    {
                        logFile.WriteLine("IOException on file: {0}\t {1}.{2}", file.FullName, file.NewName, file.Extension);
                    }
                    catch (Exception ex)
                    {
                        logFile.WriteLine("{0}{1}\t {2}.{3}", ex.ToString(), file.FullName, file.NewName, file.Extension);
                    }
                }
            }
            finally
            {
                logFile.Close();
            }
        }

        /// <summary>
        /// Stores a list of files that match the RegEx property in the Files property.
        /// </summary>
        /// <param name="directory"></param>
        public void GetFileNames(object topDirectory = null)
        {
            string directory;

            if (topDirectory == null)
            {
                directory = this.Folder;
            }
            else
            {
                directory = (string)topDirectory;
            }

            this.Files = this.GetFileNamesHelper(directory);
        }

        private List<FileName> GetFileNamesHelper(string directory)
        {
            List<FileName> files = new List<FileName>();

            files.AddRange(this.GetFileNamesFromSubDirectories(directory));
            files.AddRange(this.GetFileNamesFromCurrentDirectory(directory));

            return files;
        }

        /// <summary>
        /// Get a list of sub-directories and recursively call this GetFileNames on each one.
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        private List<FileName> GetFileNamesFromSubDirectories(string directory)
        {
            List<FileName> files = new List<FileName>();

            string[] subDirectories = Directory.GetDirectories(directory);
            foreach (string subDirectory in subDirectories)
            {
                files.AddRange(this.GetFileNamesHelper(subDirectory));
            }

            return files;
        }

        private List<FileName> GetFileNamesFromCurrentDirectory(string directory)
        {
            List<FileName> files = new List<FileName>();

            string[] results = Directory.GetFiles(directory);

            foreach (string s in results)
            {
                FileName newfile = new FileName();
                newfile.FullName = s;

                if (newfile.IsValid)
                {
                    if (this.DoesFileMatchRegex(newfile.Name))
                    {
                        if (this.ShouldSuggestFix)
                        {
                            if (this.CapsFix)
                            {
                                newfile.NewName = this.ConstructNewFileNameUpper(newfile.Name);
                            }
                            else
                            {
                                newfile.NewName = this.ConstructNewFileName(newfile.Name);
                            }
                        }

                        files.Add(newfile);
                    }
                }
            }

            return files;
        }

        private bool DoesFileMatchRegex(string oldFileName)
        {
            return Regex.IsMatch(oldFileName, this.RegEx);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="oldFileName"></param>
        /// <returns></returns>
        private string ConstructNewFileName(string oldFileName)
        {
            string[] namePieces = oldFileName.Split('-');

            string newFileName = namePieces[0] + "-" + namePieces[1] + "-" + namePieces[2] + "-" + namePieces[3] + "-" + namePieces[5] + "-" + namePieces[4];
            for (int i = 6; i < namePieces.Length; i++)
                newFileName += "-" + namePieces[i];

            return newFileName;
        }

        private string ConstructNewFileNameUpper(string oldFileName)
        {
            return oldFileName.ToUpper();
        }
    }
}
